/* tourOff.java
 * tourOff is an offering of a created tour.
 * people reserve this tourOff, not actual tour object.
 * object contains a tour object, offering name, and start date.
 * 
 * Greg Warner
 * Derek Dupuis
 * Michael Dixey
 * Alex Schwartz
 */

import java.util.*;
import java.text.*;


public class TourOff
{
   //---------variables----------
   private Tour tourObject;
   private String offeringName;
   private GregorianCalendar startDate;
   private int size;
   private int roomsNeeded;
   
   private ReservationColl reservations;
       
   public TourOff( Tour tour, String offN, GregorianCalendar sD )
   {
      tourObject = tour;
      offeringName = offN;
      startDate = sD;
      reservations = new ReservationColl();
      size = 0;
      roomsNeeded = 0;
   }
   
   //-------------------accessor methods-----------------
   public Tour tour() { return tourObject; }
   
   public GregorianCalendar startDate() { return startDate; }
   
   public String offeringName() { return offeringName; }
   
   public ReservationColl reservations() { return reservations; } 
   
   public int size() { return size; }
   
   public int roomsNeeded() { return roomsNeeded; }
   
   public void setRoomsNeeded( int r ) { roomsNeeded = r; }
   
   public String city() { return tourObject.city(); }
   
   public String state() { return tourObject.state(); }
   
   public Reservation getReservation( String s )
   {
      return reservations.get( s );
   }
   
   //---------------------------------------------------
   
   //addReservation(Reservation r)
   public boolean addReservation( Reservation r )
   {
      if( r.status().compareTo( "double" ) == 0 ){
         if( (size+2) > tourObject.capacity() ){
            return false;
         }
         size = size + 2;
      }
      else if( (size+1) > tourObject.capacity() ){
            return false;
      }
      else{
         size = size + 1;
      }
      return reservations.add( r );
   }
   
   public void match()
   {
       // iterate through reservation list, adding up all doubles and 
       // singles, and adding all solos to individual treemaps based on
       // gender and sorted by age.
       int rmNum = 1;
       ArrayList< Reservation > maleList, femaleList;
       
       maleList = new ArrayList< Reservation >();
       femaleList = new ArrayList< Reservation >();
      
       //---------Count up singles & doubles, extract Solos---------
       Set r = reservations.keySet();
       Iterator iter = r.iterator();
       while( iter.hasNext() )
       {
           Reservation res = reservations.get( iter.next() );
           if( res.status().compareTo( "single" ) == 0 ){
              res.setRoomNumber( rmNum++ );
           }
           else if( res.status().compareTo( "double" ) == 0 ){
               res.setRoomNumber( rmNum++ );
           }
           else
           {
               if( res.gender() == 1 )
               {
                   int i;
                   for( i = 0; i < maleList.size(); i++ )
                   {
                       if( res.age() < maleList.get( i ).age() )
                           break;
                   }
                   maleList.add( i, res );
               }
               else
               {
                   int i;
                   for( i = 0; i < femaleList.size(); i++ )
                   {
                       if( res.age() < femaleList.get( i ).age() )
                           break;
                   }
                   femaleList.add( i, res );
               }
           }
       }
       //-----------lists set up - singles & doubles done----------
       
       
       // ----------------------Match & count up Solos-------------
       // go through maleList and match by age
       for( int i = 0; i < maleList.size(); i += 2 )
       {
           maleList.get( i ).setRoomNumber( rmNum );
           
           try
           {
               maleList.get( i + 1 ).setRoomNumber( rmNum );
               maleList.get( i ).setPartner( maleList.get( i + 1 ).travelerName() );
               maleList.get( i + 1 ).setPartner( maleList.get( i ).travelerName() );
           }
           catch( Exception e ){}
           rmNum++;
       }
       
       // go through femaleList and match by age
       for( int i = 0; i < femaleList.size(); i += 2 )
       {
           femaleList.get( i ).setRoomNumber( rmNum );
           try
           {
               femaleList.get( i + 1 ).setRoomNumber( rmNum );
               femaleList.get( i ).setPartner( femaleList.get( i + 1 ).travelerName() );
               femaleList.get( i + 1 ).setPartner( femaleList.get( i ).travelerName() );
           }
           catch( Exception e ){}
           rmNum++;
       }
       
       // final room count = rmCount
       setRoomsNeeded( rmNum-1 );
   }
   
   
   public String printTravelPlans()
   {
       // go through the reservation list and print out each travelers
       // itinerary for travel to and from the tour location
       String s = "";
       Set r = reservations.keySet();
       Iterator iter = r.iterator();
       while( iter.hasNext() )
       {
           Reservation res = reservations.get( iter.next() );
           String name = res.travelerName();
           GregorianCalendar start, depart;
           DateFormat tF = DateFormat.getTimeInstance( DateFormat.SHORT );
           DateFormat dF = DateFormat.getDateInstance( DateFormat.SHORT );
           
           start = (GregorianCalendar)startDate.clone();
           start.add( Calendar.DAY_OF_MONTH, 
                     tour().events().get( 0 ).startTime().get( Calendar.DAY_OF_MONTH ) 
                         - 1);
           start.add( Calendar.HOUR_OF_DAY,
                     tour().events().get( 0 ).startTime().get( Calendar.HOUR_OF_DAY ) );
           start.add( Calendar.MINUTE,
                     tour().events().get( 0 ).startTime().get( Calendar.MINUTE ) );
           
           if( res.status().compareTo( "double" ) == 0 )
              s += name + " & " + res.partner();
           else
              s += name;
           
           // get the city and state of the tour, and compare to traveler
           if( tourObject.state().compareTo( res.state() ) == 0 )
           {
               if( tourObject.city().compareTo( res.city() ) == 0 )
               {
                   // traveler can walk to the tour location
                   // calculate departure time from tour start time
                   depart = (GregorianCalendar)start.clone();
                   depart.add( Calendar.MINUTE, -30 );
                   
                  s += String.format( ": -----\n\tWalk   at %2s, %2s - %s to Tour Start\n",
                                     tF.format(depart.getTime()),
                                     dF.format(depart.getTime()), res.city());
               }
               else
               {
                   // the traveler must take a taxi to starting location
                   // calculate departure time from tour start time
                   depart = (GregorianCalendar)start.clone();
                   depart.add( Calendar.MINUTE, -30 );
                   
                   s += String.format( ": -----\n\tTaxi   at %2s, %2s - %s to Tour Start\n",
                                      tF.format( depart.getTime() ), 
                                      dF.format( depart.getTime() ), res.city() );
               }
           }
           else
           {
               // traveler must take a plane to state, then taxi to city
               // calculate departure time from tour start time
               depart = (GregorianCalendar)start.clone();
               depart.add( Calendar.HOUR_OF_DAY, -5 );
               depart.add( Calendar.MINUTE, 30 );
               
               s+= String.format( ": -----\n\tFlight at %2s, %2s - %s airport to %s airport\n",
                                 tF.format( depart.getTime() ), 
                                 dF.format( depart.getTime() ), res.city(),
                                 tourObject.state() );
               
               depart = (GregorianCalendar)start.clone();
               depart.add( Calendar.MINUTE, -30 );
               
               s += String.format( "\tTaxi   at %2s, %2s - %s airport to Tour Start\n",
                                  tF.format( depart.getTime() ),dF.format( depart.getTime()),
                                  tourObject.state() );
           }
       }
       
       return s;
   }
   
   //prints the tourOff with start date, offeringName.
   //also prints the tour information from the tour object.
   //finally, prints the amount of travelers, as the capacity needed.
   public String toString()
   {
     
      String s = offeringName + " --- on " + startDate.get( Calendar.DAY_OF_MONTH );
      s = s + "/" + (startDate.get(Calendar.MONTH) + 1);
      s = s + "/" + startDate.get(Calendar.YEAR) + " : \n\t";
      s = s + tourObject.toStringBasic();
      s = s + "\tTravelers: " + size + "\tRooms Needed: " + roomsNeeded +"\n";
      s = s + reservations.toString();
      return s;
   }
 
}

